home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
United Public Domain Gold 4
/
United Public Domain Gold 4.iso
/
fredfish
/
ff.0014.dms
/
ff.0014.adf
/
dex
/
dex1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-04-10
|
13KB
|
540 lines
/************************************************************************
* *
* Copyright (c) 1982, Fred Fish *
* All Rights Reserved *
* *
* This software and/or documentation is released for public *
* distribution for personal, non-commercial use only. *
* Limited rights to use, modify, and redistribute are hereby *
* granted for non-commercial purposes, provided that all *
* copyright notices remain intact and all changes are clearly *
* documented. The author makes no warranty of any kind with *
* respect to this product and explicitly disclaims any implied *
* warranties of merchantability or fitness for any particular *
* purpose. *
* *
************************************************************************
*/
/*
* FILE
*
* dex1.c dynamic reconfiguration functions
*
* KEY WORDS
*
* dex files
* dex
*
* DESCRIPTION
*
* This file contains functions for doing dynamic
* reconfiguration. DEX automatically searches
* a directory for a reconfiguration file the first
* time any file in that directory is processed.
* The default reconfiguration file is ".dexrc" but
* can be changed to any desired file via a command
* line switch.
*
* FUNCTIONS
*
* make_entry make an entry in the name table
* reconfig do dynamic reconfiguration
* rc_name build reconfiguration name
* do_reconfig process open reconfiguration file
* do_flags process reconfiguration ".flags" line
* file_out process reconfiguration ".output" line
*
* AUTHOR
*
* Fred Fish
*
*/
#include <stdio.h>
#include "hashtbl.h"
#include "dex.h"
extern int debug; /* Global debug flag */
extern int vflag; /* Global verbose flag */
extern char *get_memory ();
static struct flgwrd { /* Reconfiguration flags */
char *word; /* String form of flag */
int flag; /* Token form of flag */
};
static struct flgwrd flgwrds[] = { /* Flags recognized */
"PROCESS", PROCESS,
"EMITTEXT", EMITTEXT,
"EMITBOX", EMITBOX,
"EMITFILL", EMITFILL,
"EMITUL", EMITUL,
"EMITBP", EMITBP,
"REGION", REGION,
NULL, NULL /* Marks end of flags list */
};
/*
* FUNCTION
*
* make_entry make an entry in table with specified name
*
* KEY WORDS
*
* hash table insertion
*
* SYNOPSIS
*
* struct tbl_data *make_entry(name)
* char *name;
*
* DESCRIPTION
*
* Make_entry allocates memory for a table entry, initializes
* it's name field, and then adds it to the hash table.
* Each entry name is actually the string which is recognized
* as starting a new documentation section, such as
* "FUNCTION" or "DESCRIPTION".
*
* Note that make_entry allocates fresh memory for the name
* string, and copies the name there. This insures that the
* characters comprising the entry's name do not vanish
* when somebody's stack is popped.
*
*/
/*
* PSEUDO CODE
*
* Begin make_entry
* Initialize entry pointer to NULL.
* If name pointer is not invalid then
* Get memory for the entry name.
* If memory was allocated then
* Copy the name to the fresh memory.
* Get memory for the table data structure.
* If memory was allocated then
* Remember the name of the entry.
* Add entry to table, getting pointer.
* End if
* End if
* End if
* Return table entry pointer.
* End make_entry
*
*/
static struct tbl_data *make_entry(name)
char *name;
{
struct tbl_data *temp, *tbl_add();
char *name_save;
temp = NULL;
if (name != NULL) {
name_save = (char *) get_memory(strlen(name)+1);
if (name_save != NULL) {
strcpy(name_save,name);
temp = (struct tbl_data *) get_memory(sizeof(struct tbl_data));
if (temp != NULL) {
temp->name = name_save;
temp = tbl_add(temp);
if (debug) {printf("make_entry: added \"%s\"\n",temp->name);}
}
}
}
return(temp);
}
/*
* FUNCTION
*
* reconfig do dynamic reconfiguration if necessary
*
* KEY WORDS
*
* dynamic reconfiguration
* reconfiguration routines
*
* SYNOPSIS
*
* reconfig(pfn,rcfn)
* char *pfn; (processed file name)
* char *rcfn; (rc file base name)
*
* DESCRIPTION
*
* Tests to see if a new reconfiguration file needs to
* be processed and if so, opens it and calls routine
* to actually do the reconfiguration.
*
*/
/*
* PSEUDO CODE
*
* Begin reconfig
* Build reconfiguration file name.
* If name is not same as last used name then
* If the reconfiguration file can be opened
* Do the reconfiguration.
* Remember name of reconfig file.
* Close the reconfiguration file.
* End if
* End if
* End reconfig
*
*/
static char last_rcfile[MAXNAMESIZE];
reconfig(pfn,rcfn)
char *pfn;
char *rcfn;
{
char buffer[MAXNAMESIZE];
FILE *rcfp, *fopen();
rc_name(buffer,pfn,rcfn);
if (debug) {printf("reconfig: %s & %s => %s\n",pfn,rcfn,buffer);}
if (strcmp(buffer,last_rcfile) != 0) {
if ((rcfp = fopen(buffer,"r")) != NULL) {
if (vflag) {printf("dex: reconfiguring using \"%s\"\n",buffer);}
do_reconfig(rcfp);
strcpy(last_rcfile,buffer);
fclose(rcfp);
}
}
}
/*
* FUNCTION
*
* rc_name build the reconfiguration file name
*
* KEY WORDS
*
* dynamic reconfiguration
* reconfiguration file
*
* SYNOPSIS
*
* static rc_name(out,pfn,rcfn)
* char *out; (output goes here)
* char *pfn; (processed file name)
* char *rcfn; (rc base file name)
*
* DESCRIPTION
*
* Builds the name used when an attempt is made to open
* the reconfiguration file. Assumes that if the specified
* base reconfiguration file name does not contain a slash character
* "/" then any prefix in the processed file name is to be
* extracted and prepended to the specified base reconfiguration
* file name.
*
* For example, if the processed file name is "/usr/me/myfile"
* and the base reconfiguration file name is
* ".dexrc" then the name used to open the reconfiguration
* file will be "/usr/me/.dexrc".
* If however the base reconfiguration file name is
* "/usr/me/newrc" then this name will simply be
* returned unchanged
*
* This seems to be the best way of handling reconfiguration
* file names since if the full pathname is given then
* only that file will be used regardless of where the
* processed file is. However a generic name may be
* given (such as ".dexrc") in which case a search will
* be made in the processed file's directory for a file
* with that generic name.
*
*/
/*
* PSEUDO CODE
*
* Begin rc_name
* If the specified base rc file name contains "/"
* Copy that name to output.
* Else
* Copy processed file name to work buffer.
* If processed file name has no last "/" in it then
* Simply copy base rc file name to output.
* Else
* Append base rc file name after last "/"
* Copy concatenated names to output.
* End if
* End if
* End rc_name
*
*/
static rc_name(out,pfn,rcfn)
char *out; /* Pointer to output place */
char *pfn; /* Pointer to processed file name */
char *rcfn; /* Pointer to reconfig base file name */
{
char buffer[MAXNAMESIZE]; /* Concatenation work buffer */
char *cp; /* Work pointer for name build */
char *rindex(); /* Pointer to last occurrence of char */
if (index(rcfn,'/') != NULL) {
strcpy(out,rcfn);
} else {
strcpy(buffer,pfn);
cp = rindex(buffer,'/');
if (cp == NULL) {
strcpy(out,rcfn);
} else {
strcpy(++cp,rcfn);
strcpy(out,buffer);
}
}
}
/*
* FUNCTION
*
* do_reconfig process open reconfiguration file
*
* KEY WORDS
*
* dynamic reconfiguration
* reconfiguration routines
*
* SYNOPSIS
*
* do_reconfig(rcfp)
* FILE *rcfp;
*
* DESCRIPTION
*
* Reads each record from the currently open reconfiguration
* file, creating table entries if necessary, and adding
* the reconfiguration information to the specified table
* entries.
*
*/
/*
* PSEUDO CODE
*
* Begin do_reconfig
* While a record can be read from reconfiguration file
* Zap the newline at the end.
* Skip over any leading whitespace.
* If the line has something useful then
* Extract the option field.
* Skip to start of next field.
* If the option is to process flags then
* Process all flags on the line.
* Else if option is change output file
* Change name of output file.
* Else
* Print warning message.
* End if
* End if
* End while
* End do_reconfig
*
*/
do_reconfig(rcfp)
FILE *rcfp;
{
char buffer[256];
char string[128];
char *cp, *skpbt(), *xfield();
while (fgets(buffer,sizeof(buffer),rcfp) != NULL) {
buffer[strlen(buffer)-1] = NULL;
cp = skpbt(buffer);
if (*cp != '#' && *cp != NULL && *cp != '\014') {
cp = xfield(string,cp);
cp = skpbt(cp);
if (strcmp(string,".flags") == 0) {
do_flags(cp);
} else if (strcmp(string,".output") == 0) {
file_out(cp);
} else {
fprintf(stdout,"dex: \"%s\" reconfiguration action?\n",string);
}
}
}
}
/*
* FUNCTION
*
* do_flags process flags for specified section
*
* KEY WORDS
*
* dynamic reconfiguration
* flags
*
* SYNOPSIS
*
* do_flags(flags_line)
* char *flags_line;
*
* DESCRIPTION
*
* Processes all flags for the current section, setting
* or resetting those specified. Flags not specified are
* unchanged from the default (reset).
*
* Flags may begin with an explicit action character
* "-" or "+" for reset or set respectively. The
* default is to set the named flag.
*
*/
/*
* PSEUDO CODE
*
* Begin do_flags
* If the passed pointer is not invalid then
* If there is a line to process then
* Extract the name of the section.
* Skip to next field (first flag).
* If the section is not in table
* Create a new table entry.
* End if
* While there is a flag field left
* Extract flag field.
* Skip to next field.
* Init flag field pointer.
* If explicit state character
* Skip over it.
* End if
* For each entry in flags list
* If entry matches flag string
* If reset requested
* Reset flag.
* Else
* Set flag.
* End if
* Break for loop
* End if
* End for
* End while
* End if
* End if
* End do_flags
*
*/
static do_flags(cp)
char *cp;
{
char string[128];
char *xfield(), *skpbt();
struct tbl_data *rp, *make_entry(), *tbl_find();
struct flgwrd *flagp;
char *stp;
if (cp != NULL) {
if (*cp != NULL) {
cp = xfield(string,cp);
cp = skpbt(cp);
if (debug) {printf("do_flags: region \"%s\"\n",string);}
if ((rp = tbl_find(string)) == NULL) {
rp = make_entry(string);
}
while (*cp != NULL) {
cp = xfield(string,cp);
cp = skpbt(cp);
if (debug) {printf("do_flags: got flag \"%s\"\n",string);}
stp = string;
if (*stp == '-' || *stp == '+') {
stp++;
}
for (flagp = flgwrds; flagp->word != NULL; flagp++) {
if (strcmp(flagp->word,stp) == 0) {
if (string[0] == '-') {
rp->flags &= ~(flagp->flag);
} else {
rp->flags |= flagp->flag;
}
break;
}
}
}
}
}
}
/*
* FUNCTION
*
* file_out reconfigure for new output file
*
* KEY WORDS
*
* dynamic reconfiguration
* output file
*
* SYNOPSIS
*
* file_out(file_line)
* char *file_line;
*
* DESCRIPTION
*
* Saves file name for output collection when specified
* section is processed. Note that the name must
* be stuffed safely away in static memory since
* it will go away when one of this routines ancestors
* exits.
*
*/
/*
* PSEUDO CODE
*
* Begin file_out
* If passed pointer is not invalid then
* If there is a line to use then
* Extract name of section.
* Skip to file name field.
* If section is not in table
* Create a new table entry.
* End if
* Extract name of file.
* Allocate some static memory.
* Save the name in static memory.
* Remember where it is.
* End if
* End if
* End file_out
*
*/
file_out(cp)
char *cp;
{
char string[128];
char *xfield(), *skpbt();
struct tbl_data *rp, *make_entry(), *tbl_find();
char *file_save;
if (cp != NULL) {
if (*cp != NULL) {
cp = xfield(string,cp);
cp = skpbt(cp);
if ((rp = tbl_find(string)) == NULL) {
rp = make_entry(string);
}
cp = xfield(string,cp);
file_save = (char *) get_memory(strlen(string)+1);
strcpy(file_save,string);
rp->out = file_save;
if (debug) {printf("file_out: out file \"%s\"\n",rp->out);}
}
}
}